/*
 * Copyright 2008 Yuan-Chu Tai
 * http://sourceforge.net/projects/jxa
 *
 * This file is part of JXAC. JXAC is free software, developed at university.
 * You can redistribute it and/or modify it under the terms of the GNU General 
 * Public License as published by the Free Software Foundation; 
 * either version 2 of the License, or (at your option) any later version.
 * JXAC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
 * PURPOSE.  See the GNU General Public License for more details.
 * You should have received a copy of the GNU General Public License along with mobber;
 * if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
 * Boston, MA 02111-1307 USA .
 */
 
import net.sourceforge.jxa.*;
import java.io.*;
import java.util.*;
import javax.microedition.midlet.*;
import javax.microedition.rms.RecordStore;
import javax.microedition.rms.RecordStoreException;
import javax.microedition.rms.RecordStoreFullException;
import javax.microedition.rms.RecordStoreNotFoundException;
import javax.microedition.lcdui.*;

public class jxac extends MIDlet implements CommandListener, XmppListener {
	private Form login_form;
	private List contacts_list;
	//private Alert msg_alert;
	private TextBox send_box;
	private TextField id_field;
	private TextField passwd_field;
	private TextField server_field;
	private ChoiceGroup multiGrp;
	
	private Command log_loginCmd;
	private Command log_exitCmd;
	
	private Command main_exitCmd;
	private Command main_backgroundCmd;
	
	private Command messageList_backCmd;
	
	private Command sendBox_sendCmd;
	private Command sendBox_cancelCmd;
	
	private static Image offline_img;
	private static Image away_img;
	private static Image busy_img;
	private static Image online_img;

	
	private Buddy currentBuddy;
	private Jxa jxa;
	private Roster roster;
	private boolean started;
	Vector	buddyList;
	
	private Image loadImage(String name) {
		Image image = null;
		try {
		  image = Image.createImage(name);
		} catch (IOException ioe) {
		  System.out.println(ioe);
		}
		return image;
  }
	
	public void onConnFailed(String msg) {
		Display.getDisplay(this).setCurrent(login_form);
		
		Alert msg_alert = new Alert("Connect error",
				"Can't connect to server, please check your network", null, AlertType.ERROR);
		msg_alert.setTimeout(Alert.FOREVER );
		Display.getDisplay(this).setCurrent(msg_alert);
	}
	
	public void onAuthFailed(final String message) {
		Display.getDisplay(this).setCurrent(login_form);
		
		Alert msg_alert = new Alert("Login error",
				"Invalid username/password, please check and try again", null, AlertType.ERROR);
		msg_alert.setTimeout(Alert.FOREVER );
		Display.getDisplay(this).setCurrent(msg_alert);
	}

	public void onAuth(final String resource) {
		try {
			jxa.getRoster();
		} catch (final IOException ex) {
			ex.printStackTrace();
		}
		contacts_list.setTitle("contacts");
		
		// Check the option state and decide whether to save username&password
		int count = multiGrp.size();
		boolean[] choiceState = new boolean[count];
		multiGrp.getSelectedFlags(choiceState);	
		try {
			RecordStore login_info = RecordStore.openRecordStore("login_info", true);
			int recordSize = login_info.getNumRecords();		
			ByteArrayOutputStream baos = new ByteArrayOutputStream();
			DataOutputStream os = new DataOutputStream(baos);
			if (choiceState[0]) {
				os.writeBoolean(true);
				os.writeUTF(id_field.getString());
				os.writeUTF(passwd_field.getString());
			} else {
				os.writeBoolean(false);
			}
			byte[] data = baos.toByteArray();
			if (recordSize == 0) {
				login_info.addRecord(data, 0, data.length);
			} else {
				login_info.setRecord(1, data, 0, data.length);
			}		
			login_info.closeRecordStore();	
		} catch (RecordStoreFullException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (RecordStoreNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (RecordStoreException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		
		// Clear resources used by loggin screen
		log_exitCmd = null;
		log_loginCmd = null;
		id_field = null;
		passwd_field = null;
		server_field = null;
		login_form = null;
	}

	public void onMessageEvent(final String from, final String body) {
		Buddy srcBuddy = null;
		if (currentBuddy.jid.equals(from))
			srcBuddy = currentBuddy;
		else {
			for (int i = buddyList.size()-1; i >= 0; i--) {
				if (((Buddy) buddyList.elementAt(i)).jid.equals(from)) {
					srcBuddy = (Buddy) buddyList.elementAt(i);
					break;
				}
			}
		}
		
		if (srcBuddy == null) {
			System.out.println("Error buddy not found");
		} else {
			srcBuddy.getMessageList(messageList_backCmd, this);
			srcBuddy.receivedMessage(body);
		}
		
		
		Alert msg_alert = new Alert("from " + from, body, null, AlertType.INFO);
		msg_alert.setTimeout(Alert.FOREVER );
		Display.getDisplay(this).setCurrent(msg_alert);
		java.lang.System.out.println("*debug* message, " + from + ":" + body);
		java.lang.System.out.println("*debug* " + this.roster.get_allMessages());
	}

	public void onContactEvent(final String jid, final String name, final String group, final String subscription) {
		if (subscription.equals("both")) {
			Buddy tmp = new Buddy(jid, name, Buddy.STATUS_OFFLINE);
			this.buddyList.addElement(tmp);
			contacts_list.append(tmp.name, offline_img);
		}
	}

	public void onContactOverEvent() {}

	public void onStatusEvent(final String jid, final String show, final String status) {
		java.lang.System.out.println("*debug* onStatusEvent: " + jid + ", " + show + ", " + status);
		String jidTmp = jid.substring(0, jid.indexOf('/'));
		for (int i=0; i< buddyList.size(); i++) {
			Buddy tmpBuddy = (Buddy)buddyList.elementAt(i);
			if (jidTmp.equals(tmpBuddy.jid)) {
				if (show.equals("na")) {
					tmpBuddy.status = Buddy.STATUS_OFFLINE;
					contacts_list.set(i, tmpBuddy.name, offline_img);
					
				} else if (show.equals("away")) {
					tmpBuddy.status = Buddy.STATUS_AWAY;
					contacts_list.set(i, tmpBuddy.name, away_img);
					
				} else if (show.equals("dnd")) {
					tmpBuddy.status = Buddy.STATUS_BUSY;
					contacts_list.set(i, tmpBuddy.name, busy_img);
					
				} else {
					tmpBuddy.status = Buddy.STATUS_ONLINE;
					contacts_list.set(i, tmpBuddy.name, online_img);
				}
				
				break;
			}
		}
	}

	public void onSubscribeEvent(final String jid) {}

	public void onUnsubscribeEvent(final String jid) {}

	public void commandAction(final Command cmd, final Displayable displayable) {
		if (cmd == log_loginCmd) {
			String id = id_field.getString();
			if (id.indexOf('@') == -1)
				id = id + "@gmail.com";
			String passwd = passwd_field.getString();
			String server = server_field.getString();
			Display.getDisplay(this).setCurrent(contacts_list);
			jxa = new Jxa(id, passwd, "mobile", 10, server, "5223", true);
			jxa.addListener(this);
			jxa.start();
			
		} else if (cmd == messageList_backCmd) {
			Display.getDisplay(this).setCurrent(contacts_list);
			
		} else if (cmd == sendBox_cancelCmd) {
			jxa.sendMessage(currentBuddy.jid, send_box.getString());
			currentBuddy.sentMessage(send_box.getString());
			send_box.setString("");
			Display.getDisplay(this).setCurrent(currentBuddy.getMessageList(messageList_backCmd, this));

		} else if (cmd == sendBox_sendCmd) {
			send_box.setString("");
			Display.getDisplay(this).setCurrent(currentBuddy.getMessageList(messageList_backCmd, this));
			
		} else if (cmd == List.SELECT_COMMAND) {
			// From Main screen
			if (displayable == contacts_list) {
				currentBuddy = (Buddy) buddyList.elementAt(contacts_list.getSelectedIndex());
				Display.getDisplay(this).setCurrent(currentBuddy.getMessageList(messageList_backCmd, this));
			
			// From message list of one buddy
			} else {
				send_box.setTitle("to " + currentBuddy.name);
				Display.getDisplay(this).setCurrent(send_box);
				
			}
			
		} else if (cmd == main_backgroundCmd) {
			notifyPaused();
			
		} else if (cmd == main_exitCmd) {
			notifyDestroyed();
			
		} else if (cmd == log_exitCmd) {
			notifyDestroyed();
			
		} else {
			System.out.println("Unhandled command!");
		}
	}

	public void startApp() {
		if (started) {
//			Display.getDisplay(this).setCurrent(contacts_list);
			
		} else {
			roster = new Roster();
			
			String savedUsername = null;
			String savedPassword = null;
			boolean savedStatus = false;
			
			try {
				RecordStore login_info = RecordStore.openRecordStore("login_info", true);
				
				int recordCount = login_info.getNumRecords();
				
				if (recordCount == 1) {
					byte[] data = login_info.getRecord(1);
					DataInputStream is = new DataInputStream(new ByteArrayInputStream(data));
					savedStatus = is.readBoolean();
					
					if (savedStatus) {
						savedUsername = is.readUTF();
						savedPassword = is.readUTF();
					}
					
				}
				
				login_info.closeRecordStore();
			} catch (RecordStoreFullException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (RecordStoreNotFoundException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (RecordStoreException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			
			login_form = new Form("login");
			id_field = new TextField("ID", savedUsername, 30, TextField.ANY);
			login_form.append(id_field);
			passwd_field = new TextField("password", savedPassword, 30, TextField.PASSWORD);
			login_form.append(passwd_field);
			server_field = new TextField("server", "talk.google.com", 30, TextField.UNEDITABLE);
			login_form.append(server_field);
			multiGrp = new ChoiceGroup(null, ChoiceGroup.MULTIPLE);
			multiGrp.append("Save user&password", null);
			multiGrp.setSelectedIndex(0, savedStatus);
			//multiGrp.append("Keep password", null);
			login_form.append(multiGrp);
			
			log_exitCmd = new Command("Exit", Command.EXIT, 0);
			log_loginCmd = new Command("Login", Command.OK, 1);
			login_form.addCommand(log_exitCmd);
			login_form.addCommand(log_loginCmd);
			login_form.setCommandListener(this);
			
			// Notice: BlackBerry bind back button to Command.CANCEL
			// to make sending message more convenient, I set Command.CANCEL
			// to Send message
			main_exitCmd = new Command("Exit", Command.EXIT, 0);
			main_backgroundCmd = new Command("Background", Command.CANCEL, 1);
			contacts_list = new List("connecting...", List.IMPLICIT);
			contacts_list.addCommand(main_exitCmd);
			contacts_list.addCommand(main_backgroundCmd);
			contacts_list.setCommandListener(this);
			
			messageList_backCmd = new Command("Back", Command.BACK, 0);
			
			send_box = new TextBox(null, null, 50, TextField.ANY);
			// Notice: BlackBerry bind back button to Command.CANCEL
			// to make sending message more convenient, I set Command.CANCEL
			// to Send message
			sendBox_cancelCmd = new Command("Send & Back", Command.CANCEL, 1);
			sendBox_sendCmd = new Command("Cancel", Command.BACK, 0);
			send_box.addCommand(sendBox_cancelCmd);
			send_box.addCommand(sendBox_sendCmd);
			send_box.setCommandListener(this);
			
			online_img = loadImage("/online.png");
			away_img = loadImage("/away.png");
			busy_img = loadImage("/busy.png");
			offline_img = loadImage("/offline.png");
			Buddy.in_img = loadImage("/arrow_down.png");
			Buddy.out_img = loadImage("/arrow_up.png");
			
			buddyList = new Vector();
			
			started = true;
			
			Display.getDisplay(this).setCurrent(login_form);
		}
	}
	
	public void pauseApp () {}
  
  public void destroyApp(boolean unconditional) {}
}
